/* Copyright (C) 2009 Alvaro Morais <alvaromorais@gmail.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details at
 * http://www.gnu.org/copyleft/gpl.html
 */

#include "bfile.h"
#include <string.h>
#include <stdlib.h>
#include <libgen.h>



BFile::BFile(const string& _filename) : long_filename(_filename) , isSet(true)
{
    reCheck();
}

BFile::BFile() : isSet(false)
{
}

void BFile::reCheck()
{
    if(!isSet)
        return;

    calculateBaseName();
    calculateDirName();
    setFileMode();
}

bool BFile::IsVisible() const
{
    if(!isSet)
        return false;
    return access(long_filename.c_str(), F_OK) == 0 ;

}
void BFile::assignFilename(const string& _filename)
{
    isSet = true;
    long_filename = _filename;
    reCheck();
}

bool BFile::IsReadable() const
{
    if(!isSet)
        return false;

    return access(long_filename.c_str(), R_OK) == 0 ;
}

bool BFile::IsWritable() const
{
    if(!isSet)
        return false;

    return access(long_filename.c_str(), W_OK) == 0 ;
}

bool BFile::IsExecutable() const
{
    if(!isSet)
        return false;

    return access(long_filename.c_str(), X_OK) == 0 ;
}

bool BFile::IsDirectory() const
{
    if(!isSet)
        return false;

    return fileMode & S_IFDIR;
}

bool BFile::IsRegular() const
{
    if(!isSet)
        return false;

    return fileMode & S_IFREG;
}

bool BFile::IsBlockSpecial() const
{
    if(!isSet)
        return false;

    return fileMode & S_IFBLK;
}

bool BFile::IsCharSpecial() const
{
    if(!isSet)
        return false;

    return fileMode & S_IFCHR;
}

bool BFile::IsFifoSpecial() const
{
    if(!isSet)
        return false;

    return fileMode & S_IFREG;
}

bool BFile::IsSymbolicLink() const
{
    if(!isSet)
        return false;

    return fileMode & S_IFLNK;
}

bool BFile::IsSocket() const
{
    if(!isSet)
        return false;

    return fileMode & S_IFSOCK;
}

string BFile::BaseName() const
{
    if(!isSet)
        return false;

    return baseName;
}

string BFile::DirName() const
{
    if(!isSet)
        return string();

    return dirName;
}


void BFile::calculateBaseName()
{
    if(!isSet)
        return;
    // TODO: Check for error
    int last = 0;
    for(unsigned i= 0; i < long_filename.length(); ++i)
    {
        if(long_filename[i] == '/')
            last = i;
    }
    if(last)
        baseName = long_filename.substr(last + 1, long_filename.size()  - last);
    else
        baseName = long_filename;

}

void BFile::calculateDirName()
{
    if(!isSet)
        return;

    // TODO: Check for errors
    // I have to use old C strings here becouse basename changes the string

    char* str = strdup(long_filename.c_str());
    dirName = dirname(str);
    free(str);

}

void BFile::setFileMode()
{
    if(!isSet)
        return;
    struct stat _stat;
    stat(long_filename.c_str(), &_stat);
    fileMode = _stat.st_mode;
}


string BFile::getLongFilename()  const
{
    if(!isSet)
        return string();
    return long_filename;
}

bool BFile::IsSet() const
{
    return isSet;
}

string BFile::ExtractDirName(const string& _filename)
{
    // TODO: Check for errors
    // I have to use old C strings here becouse basename changes the string

    char* str = strdup(_filename.c_str());
    string ret = dirname(str);
    free(str);
    return ret;
}

string BFile::ExtractBaseName(const string& _filename)
{
    // TODO: Check for error
    int last = 0;
    for(unsigned i= 0; i < _filename.length(); ++i)
    {
        if(_filename[i] == '/')
            last = i;
    }
    if(last)
        return  _filename.substr(last + 1, _filename.size()  - last);
    else
        return _filename;
}
